#include "DataFile.hpp"

#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <sstream>
//debug
#include <iostream>

namespace se{

DataFile::DataFile():
	m_content(NULL),
	m_size(),
	m_iterator()
{}


DataFile::DataFile(char * fileContent, FileSize_t fileSize, bool ownsContent) :
	m_content(fileContent),
	m_size(fileSize),
	m_iterator(0),
	m_ownsContent(ownsContent)
{}


void DataFile::Load(char * fileContent, FileSize_t fileSize, bool ownsContent){
	Unload();
	m_content = fileContent;
	m_size = fileSize;
	m_iterator = 0;
	m_ownsContent = ownsContent;
}
void DataFile::Unload(){
	if(m_content && m_ownsContent) delete[] m_content;
	m_content = NULL;
}


void DataFile::Read(void* dest, uint32_t sizeToRead){
	
	if(!m_content) throw(std::runtime_error("DataFile::read(...) in an empty DataFile is forbidden"));
	
	if(sizeToRead+m_iterator>m_size){
		std::stringstream ss;
		ss<<"DataFile::read("<<dest<<","<<sizeToRead<<") into a DataFile of size "<<m_size<<" failed : iterator already at "<<m_iterator<<std::endl;
		throw(std::out_of_range(ss.str()));
	}
	
	memcpy(dest, m_content + m_iterator, sizeToRead);
	
	m_iterator += sizeToRead;
}


std::string DataFile::GetString(){
	//part for testing
	uint32_t i;
	for(i = m_iterator;i<m_size&&m_content[i]!='\0';i++);
	
	if(i==m_size){
		std::stringstream ss;
		ss<<"DataFile::GetString() into a DataFile of size "<<m_size<<" failed : iterator at "
		  <<m_iterator<<" and no NULL character was found before the end."<<std::endl;
		throw(std::out_of_range(ss.str()));
	}
	//end of testing part
	return std::string(m_content+m_iterator);
}


void DataFile::Seek(uint32_t pos){
	
	if(!m_content) throw(std::runtime_error("DataFile::seek(...) in an empty DataFile is forbidden"));
	
	m_iterator = pos;
	if(m_iterator>m_size){
		std::stringstream ss;
		ss<<"DataFile::seek("<<pos<<") into a DataFile of size "<<m_size<<" failed : iterator already at "<<m_iterator<<std::endl;
		throw(std::out_of_range(ss.str()));
	}
}


FileSize_t DataFile::GetSize() const{
	
	if(!m_content) throw(std::runtime_error("DataFile::getSize(...) in an empty DataFile is forbidden"));
	
	return m_size;
}

const char* DataFile::GetContentPtr() const{
	return m_content;
}


char DataFile::operator[](const unsigned int i) const{
	
	if(!m_content) throw(std::runtime_error("DataFile::operator[](...) in an empty DataFile is forbidden"));
	
	return m_content[i];
}


DataFile::~DataFile(){
	Unload();
}


}//namespace se
